"""
Case Type   : 系统内部使用工具
Case Name   : 使用增量备份恢复到时间点
Create At   : 2023/2/14
Owner       : @kyeleze
Description :
    1.设置参数enable_cbm_tracking=on
    2.新建目录
    3.进行初始化
    4.在备份路径内初始化一个新的备份实例
    5.执行全量备份
    6.进行增量备份
    7.使用增量备份恢复到时间点
    8.重启数据库,查询数据库状态
Expect      :
    1.成功
    2.成功
    3.成功
    4.成功
    5.成功
    6.成功
    7.恢复成功
    8.数据库状态正常
History     :
"""

import unittest
import os
import time
import re

from yat.test import macro
from yat.test import Node

from testcase.utils.Logger import Logger
from testcase.utils.CommonSH import CommonSH
from testcase.utils.Common import Common
from testcase.utils.Constant import Constant


class TestUnit(unittest.TestCase):
    def setUp(self):
        self.log = Logger()
        self.log.info(f"-----{os.path.basename(__file__)[:-3]} start-----")
        self.constant = Constant()
        self.sh_primary = CommonSH('PrimaryDbUser')
        self.com = Common()
        self.primary_user_node = Node(node='PrimaryDbUser')
        self.primary_root_node = Node(node='PrimaryRoot')
        self.parent_path = os.path.dirname(macro.DB_INSTANCE_PATH)
        self.backup_path = os.path.join(self.parent_path,
                                        "backup_set/test_dir_0211")
        self.log.info("-----检查数据库状态是否正常-----")
        status = self.sh_primary.get_db_cluster_status()
        self.assertTrue("Degraded" in status or "Normal" in status)
        self.cbm_tracking = self.com.show_param("enable_cbm_tracking")

    def test_gs_probackup(self):
        text = '--step1:设置参数enable_cbm_tracking=on expect:成功--'
        if 'on' != self.cbm_tracking:
            result = self.sh_primary.execute_gsguc(
                'set', self.constant.GSGUC_SUCCESS_MSG,
                'enable_cbm_tracking=on')
            self.assertTrue(result, '执行失败:' + text)
            result = self.sh_primary.restart_db_cluster(True)
            status = self.constant.START_SUCCESS_MSG in result \
                     or 'Degrade' in result
            self.assertTrue(status, '执行失败:' + text)
        msg = self.sh_primary.execut_db_sql('show enable_cbm_tracking;')
        self.log.info(msg)
        value = msg.splitlines()[-2].strip()
        self.assertIn('on', value, '执行失败:' + text)

        text = '--step2:新建目录 expect:成功--'
        self.log.info(text)
        init_cmd = f"mkdir {self.backup_path};"
        self.log.info(init_cmd)
        init_msg = self.primary_user_node.sh(init_cmd).result()
        self.log.info(init_msg)
        self.assertNotIn(self.constant.SQL_WRONG_MSG[1], init_msg,
                         '执行失败:' + text)

        text = '--step3:进行初始化 expect:成功--'
        self.log.info(text)
        init_cmd = f"source {macro.DB_ENV_PATH};gs_probackup init -B " \
                   f"{self.backup_path};"
        self.log.info(init_cmd)
        init_msg = self.primary_user_node.sh(init_cmd).result()
        self.log.info(init_msg)
        self.assertIn(self.constant.init_success, init_msg, '执行失败:' + text)

        text = '--step4:在备份路径内初始化一个新的备份实例 expect:成功--'
        self.log.info(text)
        init_cmd = f"source {macro.DB_ENV_PATH};" \
                   f"gs_probackup add-instance " \
                   f"-B {self.backup_path} " \
                   f"-D {macro.DB_INSTANCE_PATH} --instance=pro1;"
        self.log.info(init_cmd)
        init_msg = self.primary_user_node.sh(init_cmd).result()
        self.log.info(init_msg)
        self.assertIn("'pro1' " + self.constant.init_success, init_msg,
                      '执行失败:' + text)

        text = '--step5:执行全量备份 expect:成功--'
        self.log.info(text)
        backup_cmd = f"source {macro.DB_ENV_PATH};" \
                     f"gs_probackup backup   " \
                     f"-B {self.backup_path} --instance=pro1 -b full " \
                     f"-d {self.primary_user_node.db_name} -p " \
                     f"{self.primary_user_node.db_port} ; "
        self.log.info(backup_cmd)
        backup_msg = self.primary_user_node.sh(backup_cmd).result()
        self.log.info(backup_msg)
        self.assertIn('completed', backup_msg, '执行失败:' + text)

        text = '--step6:进行增量备份 expect:成功--'
        self.log.info(text)
        backup_cmd = f"source {macro.DB_ENV_PATH};" \
                     f"gs_probackup backup " \
                     f"-B {self.backup_path} " \
                     f"--instance=pro1 -b ptrack " \
                     f"-d {self.primary_user_node.db_name} -p " \
                     f"{self.primary_user_node.db_port} ; "
        self.log.info(backup_cmd)
        backup_msg = self.primary_user_node.sh(backup_cmd).result()
        self.log.info(backup_msg)
        self.assertIn('completed', backup_msg, '执行失败:' + text)

        text = '--step7:使用增量备份恢复到时间点 expect:成功--'
        self.log.info(text)
        backupmsg = re.findall("Backup .*? completed", backup_msg)
        self.log.info(backupmsg)
        backup_id = backupmsg[0].split()[1]
        self.log.info('备份ID为：' + backup_id)
        self.log.info('----获取增量备份的Recovery Time--')
        cmd = f"source {macro.DB_ENV_PATH};" \
              f"gs_probackup show -B {self.backup_path} " \
              f"--instance=pro1|grep {backup_id}"
        backup_set = self.primary_user_node.sh(cmd).result()
        self.log.info(backup_set)
        recovery_time = backup_set.strip().split()[3] +\
                        ' ' + backup_set.strip().split()[4]
        self.log.info('----恢复到时间点----')
        stop_msg = self.sh_primary.stop_db_cluster()
        self.log.info(stop_msg)
        self.assertTrue(stop_msg, '停止集群失败')
        restore_cmd = f"source {macro.DB_ENV_PATH};" \
                      f"gs_probackup restore " \
                      f"-B {self.backup_path}  --instance=pro1 " \
                      f"-i {backup_id} --incremental-mode=checksum " \
                      f"--recovery-target-time=\"{recovery_time}\" " \
                      f"--recovery-target-inclusive=true"
        self.log.info(restore_cmd)
        restore_msg = self.primary_user_node.sh(restore_cmd).result()
        self.log.info(restore_msg)
        self.assertIn(f"Restore of backup {backup_id} completed",
                      restore_msg)

        text = '--step8:重启数据库,查询数据库状态 expect:数据库状态正常'
        self.log.info(text)
        start_msg = self.sh_primary.start_db_cluster()
        self.log.info(start_msg)
        status = self.sh_primary.get_db_cluster_status()
        self.assertTrue("Degraded" in status or "Normal" in status)

    def tearDown(self):
        text = '--清理环境--'
        self.log.info(text)
        result = self.sh_primary.execute_gsguc(
            'set', self.constant.GSGUC_SUCCESS_MSG,
            f'enable_cbm_tracking={self.cbm_tracking}')
        self.assertTrue(result, '执行失败:' + text)
        result = self.sh_primary.restart_db_cluster(True)
        status = self.constant.START_SUCCESS_MSG in result \
                 or 'Degrade' in result
        self.assertTrue(status, '执行失败:' + text)
        clear_cmd = f"rm -rf {self.backup_path};"
        self.log.info(clear_cmd)
        clear_msg = self.primary_user_node.sh(clear_cmd).result()
        self.log.info(clear_msg)
        self.log.info(f"-----{os.path.basename(__file__)[:-3]} end-----")

